package cn.qj.ymcc.service.impl;

import cn.qj.ymcc.CourseFeignAPI;
import cn.qj.ymcc.constants.BusinessConstants;
import cn.qj.ymcc.domain.*;
import cn.qj.ymcc.dto.CourseDto;
import cn.qj.ymcc.dto.CourseInfoDto;
import cn.qj.ymcc.dto.PlaceOrderDto;
import cn.qj.ymcc.dto.UpdateOrderStatusDto;
import cn.qj.ymcc.exception.GlobleBusinessException;
import cn.qj.ymcc.mapper.CourseOrderMapper;
import cn.qj.ymcc.result.JSONResult;
import cn.qj.ymcc.service.ICourseOrderItemService;
import cn.qj.ymcc.service.ICourseOrderService;
import cn.qj.ymcc.util.CodeGenerateUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale
 * @since 2025-07-30
 */
@Service
@Slf4j
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private CourseFeignAPI courseFeignAPI;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private CourseOrderMapper courseOrderMapper;
    /**
     * 生成订单和订单明细的
     *
     * @param placeOrderDto
     * @return
     */
    @Override
    public String placeOrder(PlaceOrderDto placeOrderDto) {
        List<Long> courseIds = placeOrderDto.getCourseIds();
        Integer payType = placeOrderDto.getPayType();
        String token = placeOrderDto.getToken();
        Integer type = placeOrderDto.getType();
        // 1. 校验参数
        if (courseIds == null || courseIds.isEmpty()) {
            throw new IllegalArgumentException("参数不能为空");
        }
        // 2. token校验
        Long loginId = 3l; //登陆人
        Long courseId = courseIds.get(0);
        String key = String.format(BusinessConstants.REDIS_PREVENT_REPEAT_SUBMIT_ORDER,loginId,courseId);
        Object redisToken = redisTemplate.opsForValue().get(key);
        if(redisToken == null || redisToken.toString().equals(token)){
            throw new GlobleBusinessException("请勿重复提交订单");
        }
        // 3. 生成订单
        //3.1 t_course_order   需要远程调用course服务
        String join = StringUtils.join(courseIds, ",");
        JSONResult jsonResult = courseFeignAPI.info(join);
        Object data = jsonResult.getData();

        String jsonString = JSONObject.toJSONString(data);
        //courseInfoDto
        CourseInfoDto courseInfoDto = JSONObject.parseObject(jsonString, CourseInfoDto.class);

        BigDecimal totalAmount = courseInfoDto.getTotalAmount();
        List<CourseDto> courseInfos = courseInfoDto.getCourseInfos();

        //创建courseOrder
        CourseOrder courseOrder = new CourseOrder();
        Date date = new Date();
        courseOrder.setCreateTime(date);
        courseOrder.setUpdateTime(date);
        //生成一个随机的orderNo
        String orderNo = CodeGenerateUtils.generateOrderSn(loginId);
        courseOrder.setOrderNo(orderNo);
        courseOrder.setPayType(payType);
        courseOrder.setTotalAmount(totalAmount);
        courseOrder.setTotalCount(courseIds.size());
        courseOrder.setStatusOrder(CourseOrder.PAY_STATUS_NO);
        courseOrder.setUserId(loginId);
        courseOrder.setTitle(courseInfos.get(0).getCourse().getName());
        //insert(courseOrder);

        //t_course_order_item 订单明细操作
        List<CourseOrderItem> courseOrderItems = new ArrayList<>();
        for (CourseDto courseInfo : courseInfos) {
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setCreateTime(date);
            courseOrderItem.setUpdateTime(date);
            courseOrderItem.setAmount(courseInfo.getCourseMarket().getPrice());
            courseOrderItem.setCourseId(courseInfo.getCourse().getId());
            courseOrderItem.setCourseName(courseInfo.getCourse().getName());
            courseOrderItem.setCoursePic(courseInfo.getCourse().getPic());
            courseOrderItem.setOrderNo(orderNo);
            courseOrderItem.setCount(1);
            courseOrderItems.add(courseOrderItem);
        }
        courseOrder.setCourseOrderItems(courseOrderItems);
        //添加订单明细
        //courseOrderItemService.insertBatch(courseOrderItems);

        //准备一个payOrder
        PayOrder payOrder = new PayOrder();
        payOrder.setCreateTime(date);
        payOrder.setUpdateTime(date);
        payOrder.setOrderNo(orderNo);
        payOrder.setPayType(payType);
        payOrder.setAmount(totalAmount);
        payOrder.setUserId(loginId);
        payOrder.setSubject(courseInfos.get(0).getCourse().getName());
        payOrder.setPayStatus(PayOrder.PAY_STATUS_NO);


        //发送事务消息
        //消息内容到底应该长成什么样子？
        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                //事务监听器组名字
                BusinessConstants.MQ_COURSEORDER_PAY_GROUP_TRANSACTION,
                //主题：标签
                BusinessConstants.MQ_TOPIC_ORDER + ":" + BusinessConstants.MQ_TAGS_COURSEORDER_PAY_ORDER,
                //消息：用作保存支付单
                MessageBuilder.withPayload(JSONObject.toJSONString(payOrder)).build(),
                //参数：用作保存课程订单和明细
                courseOrder);

        SendStatus sendStatus = transactionSendResult.getSendStatus();
        if(sendStatus != SendStatus.SEND_OK){
            throw new GlobleBusinessException("事务消息发送失败");
        }
        //发送延迟消息 处理超时未支付
        SendResult sendResult = rocketMQTemplate.syncSend(
                BusinessConstants.ROCKETMQ_TOPIC_ORDER_LEAVE_TIMEOUT + ":" + BusinessConstants.ROCKETMQ_TAGS_ORDER_LEAVE_TIMEOUT,
                MessageBuilder.withPayload(orderNo).build(),
                3000,
                3);//30秒后消费
        log.info("发送消息的结果：{}", sendResult);
        if(sendResult.getSendStatus() != SendStatus.SEND_OK){
            log.error("发送延迟消息失败:{}",sendResult);
            //存表 或者人工处理
        }

        //删除事务消息
        redisTemplate.delete(key);
        return orderNo;
    }

    /**
     * 保存订单和订单明细
     *
     * @param courseOrder
     */
    @Override
    public void saveOrderAndItem(CourseOrder courseOrder) {
        //防止重复提交
        Wrapper<CourseOrder> ww = new EntityWrapper<>();
        ww.eq("order_no",courseOrder.getOrderNo());
        CourseOrder courseOrderDB = selectOne(ww);
        if(courseOrderDB != null){
            throw new GlobleBusinessException("订单已存在");
        }

        //保存订单
        insert(courseOrder);
        //保存订单明细
        courseOrderItemService.insertBatch(courseOrder.getCourseOrderItems());

    }

    /**
     * 根据订单编号修改订单状态
     *
     * @param updateOrderStatusDto
     */
    @Override
    public void updateOrderStatus(UpdateOrderStatusDto updateOrderStatusDto) {
        //参数校验
        courseOrderMapper.updateOrderStatus(updateOrderStatusDto);
    }
}
